package com.cq.hd.order.factory.orderSettle;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cq.hd.common.constant.Constant;
import com.cq.hd.common.entity.hf.HfTradeAccountPay;
import com.cq.hd.common.enums.biz.OrderSettleBillTradeStateEnum;
import com.cq.hd.common.enums.biz.OrderSettleBillTradeTypeEnum;
import com.cq.hd.common.utils.GenerateUtil;
import com.cq.hd.common.utils.LocalDateUtil;
import com.cq.hd.order.api.vo.OrderSettleBillVo;
import com.cq.hd.order.config.LockUtils;
import com.cq.hd.order.mapper.TbOrderSettleBillMapper;
import com.cq.hd.order.po.TbOrderSettleBillPo;
import com.cq.hd.system.api.HfApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.MessageFormat;
import java.time.LocalDateTime;

@Component
@Slf4j
public class OrderRecoverAmtToBusinessOrderSettleBillHandler extends AbstractOrderSettleBillHandler {

    @Autowired
    private TbOrderSettleBillMapper orderSettleBillMapper;

    @Autowired
    private HfApi hfApi;

    @Override
    protected Integer getType() {
        return OrderSettleBillTradeTypeEnum.RECOVER_AMT.getValue();
    }

    @Override
    public Boolean transactAmt(OrderSettleBillVo orderSettleBillVo) {
        Long id = orderSettleBillVo.getId();

        String lockKey = MessageFormat.format(Constant.LOCK_FORMAT, "transactRecoverAmt:" + id);
        try {
            LockUtils.blockLock(lockKey, Constant.AUTO_UNLOCK_SECOND);

            TbOrderSettleBillPo tbOrderSettleBillPo = orderSettleBillMapper.selectById(id);
            if (OrderSettleBillTradeStateEnum.SUCCESS.getValue().equals(tbOrderSettleBillPo.getTradeState())) {
                log.info("订单结算商家回收金额已处理成功，orderSettleBillId：{}", id);
                return true;
            }

            // 根据reqData和reqSeqId调用余额支付查询接口做查单，如果已经支付成功则修改状态=支付成功
            LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
            String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");
            String reqSeqId = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss") + GenerateUtil.getRandomNum(5);

            HfTradeAccountPay hfTradeAccountPay = new HfTradeAccountPay();
            hfTradeAccountPay.setReqDate(yyyyMMdd);
            hfTradeAccountPay.setReqSeqId(reqSeqId);
            hfTradeAccountPay.setOrgReqDate(orderSettleBillVo.getReqDate());
            hfTradeAccountPay.setOrgReqSeqId(orderSettleBillVo.getReqSeqId());
            JSONObject queryJSONObject = hfApi.tradeAccountAmtQuery(hfTradeAccountPay).unpack();
            if (queryJSONObject != null) {
                JSONObject data = queryJSONObject.getJSONObject("data");
                String respCode = data.getString("resp_code");
                if ("00000000".equals(respCode)) {
                    // 交易状态 P:处理中；S：成功；F：失败
                    String transStat = data.getString("trans_stat");

                    if ("S".equals(transStat)) {
                        orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.SUCCESS.getValue());
                    } else if ("P".equals(transStat)) {
                        orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.PROCESSING.getValue());
                    } else if ("F".equals(transStat)) {
                        orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.FAIL.getValue());
                        orderSettleBillVo.setTradeFailReason(JSON.toJSONString(data));
                    }

                    // 如果失败，则需要重新调用余额支付的标准接口（给商户分本金），并更新订单结算记录状态
                    if (OrderSettleBillTradeStateEnum.FAIL.getValue().equals(orderSettleBillVo.getTradeState())) {
                        // 如果是重新调用余额支付接口，则请求日期和请求流水号需要用最新的
                        orderSettleBillVo.setReqDate(yyyyMMdd);
                        orderSettleBillVo.setReqSeqId(reqSeqId);
                        // 先更新流水号，避免汇付转账成功，写库失败
                        orderSettleBillMapper.updateOrderSettleBill(orderSettleBillVo);

                        hfTradeAccountPay = new HfTradeAccountPay();
                        hfTradeAccountPay.setReqDate(orderSettleBillVo.getReqDate());
                        hfTradeAccountPay.setReqSeqId(orderSettleBillVo.getReqSeqId());
                        hfTradeAccountPay.setInHfId(orderSettleBillVo.getInHfId());
                        hfTradeAccountPay.setInHfAcctId(orderSettleBillVo.getInHfAcctId());
                        hfTradeAccountPay.setGoodsDesc("订单过期未核销本金");
                        hfTradeAccountPay.setTransAmt(orderSettleBillVo.getReceiveAmt().toString());
                        JSONObject jsonObject = hfApi.tradeAccountAmtPay(hfTradeAccountPay).unpack();
                        if (jsonObject != null) {
                            data = jsonObject.getJSONObject("data");
                            // 交易状态 P:处理中；S：成功；F：失败
                            transStat = data.getString("trans_stat");

                            if ("S".equals(transStat)) {
                                orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.SUCCESS.getValue());
                            } else if ("P".equals(transStat)) {
                                orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.PROCESSING.getValue());
                            } else if ("F".equals(transStat)) {
                                orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.FAIL.getValue());
                                orderSettleBillVo.setTradeFailReason(JSON.toJSONString(data));
                            } else {
                                orderSettleBillVo.setTradeFailReason(JSON.toJSONString(data));
                            }
                        }
                    }

                    int update = orderSettleBillMapper.updateOrderSettleBill(orderSettleBillVo);
                    if (update == 0) {
                        log.error("更新订单结算商户本金支付流水记录状态失败，orderSettleBillId：{}", orderSettleBillVo.getId());
                        return false;
                    }

                    return true;
                }
            }

            // 调用余额支付的标准接口（给商户分本金）
            hfTradeAccountPay = new HfTradeAccountPay();
            hfTradeAccountPay.setReqDate(orderSettleBillVo.getReqDate());
            hfTradeAccountPay.setReqSeqId(orderSettleBillVo.getReqSeqId());
            hfTradeAccountPay.setInHfId(orderSettleBillVo.getInHfId());
            hfTradeAccountPay.setInHfAcctId(orderSettleBillVo.getInHfAcctId());
            hfTradeAccountPay.setGoodsDesc("给商户支付商品本金");
            hfTradeAccountPay.setTransAmt(orderSettleBillVo.getReceiveAmt().toString());
            JSONObject jsonObject = hfApi.tradeAccountAmtPay(hfTradeAccountPay).unpack();
            if (jsonObject != null) {
                JSONObject data = jsonObject.getJSONObject("data");
                // 交易状态 P:处理中；S：成功；F：失败
                String transStat = data.getString("trans_stat");

                if ("S".equals(transStat)) {
                    orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.SUCCESS.getValue());
                } else if ("P".equals(transStat)) {
                    orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.PROCESSING.getValue());
                } else if ("F".equals(transStat)) {
                    orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.FAIL.getValue());
                    orderSettleBillVo.setTradeFailReason(JSON.toJSONString(data));
                } else {
                    orderSettleBillVo.setTradeFailReason(JSON.toJSONString(data));
                }

                // 在提现时必须要做查单处理
                int update = orderSettleBillMapper.updateOrderSettleBill(orderSettleBillVo);
                if (update == 0) {
                    log.error("更新订单结算商户本金支付流水记录状态失败，orderSettleBillId：{}", orderSettleBillVo.getId());
                    return false;
                }
            }

            return true;
        } finally {
            LockUtils.unlock(lockKey);
        }
    }

    @Override
    public Boolean transfer(OrderSettleBillVo orderSettleBillVo) {
        return null;
    }

}
